package com.wgo.bpot.server.persist.trigger;

import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.wgo.bpot.server.persist.PersistService;


public class TriggerRegistry {
	private PersistService persistService;
	private Set<Trigger> triggers = new HashSet<Trigger>();
	private static final Logger log = Logger.getLogger(TriggerRegistry.class);

	public TriggerRegistry(PersistService persistService) {
		this.persistService = persistService;
		initializeTriggers();
	}
	
	public void invokeBefore(CrudOperation operation,Object triggerTarget){
		invokeTrigger(operation,true,triggerTarget);
	}
	 
	public void invokeAfter(CrudOperation operation,Object triggerTarget){
		invokeTrigger(operation,false,triggerTarget);
	}
	 
	private void invokeTrigger(CrudOperation operation,boolean isBefore, Object triggerTarget){
		for (Trigger trigger : triggers) {
			if (trigger.isApplicable(operation) && trigger.isApplicable(triggerTarget) && (trigger.isBefore() == isBefore)) {
				trigger.trigger(triggerTarget);
			}
		}
	}

	public void addTrigger(Trigger trigger){
		triggers.add(trigger);
	}

	public void removeTrigger(Trigger trigger){
		triggers.remove(trigger);
	}
	
	public void setTriggers(Set<Trigger> triggers) {
		this.triggers = triggers;
	}
	
	public void initializeTriggers(){
		triggers.clear();
		XStream xs = new XStream(new DomDriver());
		InputStream is = TriggerRegistry.class.getResourceAsStream("/triggers.xml");
		if (null == is) {
			log.info("No triggers defined.  /triggers.xml file does not exist in classpath.");
		}
		List<String> triggerClassNames = null;
		try {
			triggerClassNames = (List<String>)xs.fromXML(is);
		} catch (RuntimeException e) {
			log.warn("Found /triggers.xml file, but it has invalid format! I will consider this as if no triggers are defined.");
			return;
		}
		if (0 == triggerClassNames.size()) {
			log.info("No triggers defined.  /triggers.xml file does exist, but it does not have any triggers defined.");
		}
		for (String triggerClassName : triggerClassNames) {
			Class<Trigger> triggerClass = null;
			try {
				triggerClass = (Class<Trigger>)Class.forName(triggerClassName,true,Thread.currentThread().getContextClassLoader());
			} catch (ClassNotFoundException e) {
				throw new RuntimeException("Unable to load trigger class " + triggerClassName + ". Make sure it implements " + Trigger.class.getName(),e);
			}
			Trigger trigger = null;
			try {
				trigger = triggerClass.newInstance();
				trigger.setPersistService(persistService);
				triggers.add(trigger);
				log.info("Successfully registered trigger " + trigger.getClass().getSimpleName());
			} catch (Exception e) {
				log.warn("Unable to instantiate trigger: " + triggerClass.getName() + ". Make sure that the class has a default (empty) constructor.");
			}
		}
	}
	
	
}
